package cn.edu.zut.soft.graduate.fileUploadCenter.bo;

import cn.edu.soft.fastdfs.FastdfsClient;
import cn.edu.zut.soft.graduate.base.excel.ExcelWriter;
import cn.edu.zut.soft.graduate.core.constant.*;
import cn.edu.zut.soft.graduate.core.constant.config.IKEY;
import cn.edu.zut.soft.graduate.core.design.ProfessionalLever;
import cn.edu.zut.soft.graduate.core.model.Impl.Grade;
import cn.edu.zut.soft.graduate.core.model.Impl.Identity;
import cn.edu.zut.soft.graduate.core.model.Impl.Info;
import cn.edu.zut.soft.graduate.core.model.Impl.Issue;
import cn.edu.zut.soft.graduate.core.query.IdentityQuery;
import cn.edu.zut.soft.graduate.core.query.InfoQuery;
import cn.edu.zut.soft.graduate.core.query.IssueQuery;
import cn.edu.zut.soft.graduate.core.vo.IssueContent;
import cn.edu.zut.soft.graduate.core.vo.IssueVO;
import cn.edu.zut.soft.graduate.core.vo.LoginVO;
import cn.edu.zut.soft.graduate.core.vo.UserDescVO;
import cn.edu.zut.soft.graduate.gradesCenter.bo.GradeBO;
import cn.edu.zut.soft.graduate.groupCenter.bo.GroupBO;
import cn.edu.zut.soft.graduate.topicCenter.bo.IssueBO;
import cn.edu.zut.soft.graduate.userCenter.bo.IdentityBO;
import cn.edu.zut.soft.graduate.userCenter.bo.InfoBO;
import cn.edu.zut.soft.graduate.userCenter.bo.StudentBO;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by chuchuang on 16/10/30.
 */
@Repository
public class FileUploadBOImpl implements FileUploadBO {

    private Logger logger = LoggerFactory.getLogger(getClass());
    @Resource
    private FastdfsClient fastdfsClient;

    @Autowired
    private InfoBO infoBO;

    @Autowired
    private IssueBO issueBO;

    @Autowired
    private GroupBO groupBO;

    @Autowired
    private StudentBO studentBO;

    @Autowired
    private IdentityBO identityBO;

    @Resource
    private GradeBO gradeBO;

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public String upload(InputStream inputStream, String fileName, long fileSize, LoginVO loginVO) throws Exception {
        String fileId = fastdfsClient.upload(inputStream, fileSize, fileName);
        String url = fastdfsClient.getUrl(fileId);
        Map<String, String> meta = new HashMap<String, String>();
        meta.put("fileName", fileName);
        if (loginVO != null) {
            meta.put("userName", loginVO.getName());
        }
        boolean result = fastdfsClient.setMeta(fileId, meta);
        return url;
    }

    @Override
    public void downloadTeaGroupStu(OutputStream outputStream, IdentityQuery identityQuery) {
        List<Issue> issueList = getIssues(identityQuery.getGroupId());
        List<UserDescVO> teacherList = getUserDescVOs(identityQuery.getGroupId());
        List<UserDescVO> userDescVOList = studentBO.queryStuAllByTeaGroupAndAddress(identityQuery);
        List<Map<String, Object>> data = newUserDescTransformer(userDescVOList, issueList, teacherList);
        logger.warn("identityQuery = {},data length = {}",identityQuery,data.size());
        try {
            ExcelWriter.write(outputStream, IKEY.downloadTeaGroupStuSheet, IKEY.headMap, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void downloadGradeStu(OutputStream outputStream, IdentityQuery identityQuery, String key) {
        List<Issue> issueList = getIssues(identityQuery.getGroupId());
        List<UserDescVO> teacherList = getUserDescVOs(identityQuery.getGroupId());
        List<UserDescVO> userDescVOList = studentBO.queryStuAllBySystemGrade(identityQuery, key);
        List<Map<String, Object>> data = GradeStatusTransformer(userDescVOList, issueList, teacherList);
        logger.warn("identityQuery = {},data length = {}",identityQuery,data.size());
        try {
            ExcelWriter.write(outputStream, IKEY.downloadTeaGroupStuSheet, IKEY.headMap, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void downloadGuideStudent(OutputStream outputStream, Integer teaId) {
        if (teaId == null){
            return;
        }
        //该教师下题目
        InfoQuery stuInfo = new InfoQuery();
        stuInfo.setRole(Role.stu);
        stuInfo.setKey(IKEY.Guide);
        stuInfo.setValue(String.valueOf(teaId));
        stuInfo.setDel(0);
        stuInfo.setPageSize(Integer.MAX_VALUE);
        List<UserDescVO> studentInfoList = identityBO.findByInfo(stuInfo).getData();
        List<Map<String, Object>> data = getGuideStudent(studentInfoList);
        try {
            ExcelWriter.guideTeacherStudentInfo(outputStream, IKEY.downloadTeaGroupStuSheet, IKEY.headMap, data);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    @Override
    public void downloadFinalGrade(OutputStream outputStream) {
        IdentityQuery allStudent = new IdentityQuery();
        allStudent.setRole(Role.stu);
        allStudent.setDel(0);
        List<Identity> identityList = identityBO.findByQuery(allStudent).getData();
        for (Identity user : identityList){
            gradeBO.checkFinalRepolyGradeAdminRole(user.getId(), "admin");
        }
        IdentityQuery identityQuery = new IdentityQuery();
        identityQuery.setPageSize(Integer.MAX_VALUE);
        List<UserDescVO> fianlGrade = studentBO.queryStuAllBySystemGrade(identityQuery, null);
        List<Map<String, Object>> data = getGuideStudent(fianlGrade);
        try {
            ExcelWriter.guideTeacherStudentInfo(outputStream, IKEY.downloadTeaGroupStuSheet, IKEY.headMap, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private List<Issue> getIssues(Integer group) {
        IssueQuery issueQuery = new IssueQuery();
        issueQuery.clear();
        return issueBO.queryTeaGroupAll(group, issueQuery).getData();
    }
    private List<Issue> getGuideTeacherIssue(Integer teaId){
        if (teaId == null){
            return null;
        }
        IssueQuery issueQuery = new IssueQuery();
        issueQuery.clear();
        issueQuery.setIdentityId(teaId);
        issueQuery.setIssuePhase(IssuePhase.finish);
        return  issueBO.findByQuery(issueQuery).getData();
    }

    private List<UserDescVO> getUserDescVOs(Integer group) {
        InfoQuery infoQuery = new InfoQuery();
        infoQuery.setInfoType(InfoType.Group);
        infoQuery.setKey(IKEY.GROUP);
        //如果为空则检索全部指导教师
        infoQuery.setValue(group == null ? null :group.toString());
        infoQuery.setRole(Role.tea);
        infoQuery.clear();
        return identityBO.findByInfo(infoQuery).getData();
    }

    private List<Map<String, Object>> userDescTransformer(List<UserDescVO> userDescVOList, List<Issue> issueList, List<UserDescVO> teacherList) {
//        Map<Integer, IssueVO> issueVOMap = issueListTransformerMap(issueList);
//        Map<Integer, UserDescVO> teacherMap = userListTransformerMap(teacherList);
        List<Map<String, Object>> mapList = new ArrayList<>();
        Map<String, Object> map;
        Info info;
        for (UserDescVO userDescVO : userDescVOList) {
            map = new HashMap<>();
            Map<String, Info> userInfoMap = infoListTransformerTypeKeyMap(userDescVO.getInfoList());
            //0.学号
            map.put("0", userDescVO.getIdentity().getNoId());
            //1.姓名
            map.put("1", userDescVO.getIdentity().getName());
            //3.手机号
            map.put("3", userDescVO.getIdentity().getPhone());
//            for (Info info:userDescVO.getInfoList()) {
            //2.班级
            info = userInfoMap.get(InfoType.Basic + IKEY.CLAZZ);
            map.put("2", info == null ? "" : info.getValue());
            info = userInfoMap.get(InfoType.TOPIC +IKEY.TopicId);
            IssueVO issueVO = null;
            if (info != null) {
                issueVO = issueBO.getCacheIssueVO(Integer.parseInt(info.getValue()));
            }
            if (issueVO != null ) {
                //4.答辩题目
                map.put("4", issueVO.getIssue().getTitle());
                //6.校外导师
                map.put("6", issueVO.getIssueContent().getOutTeacher() == null ? "" :issueVO.getIssueContent().getOutTeacher().getName());
                //10.题目来源
                map.put("10", issueVO.getIssue().getSource().getName());
            }
            info = userInfoMap.get(InfoType.TOPIC + IKEY.ChildTopicName);
            //5.子标题
            map.put("5", info == null ? "" :info.getValue());
            info = userInfoMap.get(InfoType.Tea + IKEY.Guide);
            if (info != null){
                UserDescVO teacher = identityBO.getUserDesc(Integer.parseInt(info.getValue()));
                //7.指导教师
                map.put("7", teacher.getIdentity().getName());
                //8.职称
                Map<String, Info> infoMap = infoListTransformerTypeKeyMap(teacher.getInfoList());
                Info pro = infoMap.get(InfoType.Basic + IKEY.PROFESSIONALLEVER);
                map.put("8", pro == null ? "" : ProfessionalLever.getMap().get(pro.getValue()) == null ? pro.getValue() : ProfessionalLever.getMap().get(pro.getValue()));
            }
            //9.地区
            info = userInfoMap.get(InfoType.Basic + IKEY.ADDRESS);
            map.put("9", info == null ? Address.zhengzhou.getName() : Address.valueOf(info.getValue()).getName());
            mapList.add(map);
        }
        return mapList;
    }

    private List<Map<String, Object>> newUserDescTransformer(List<UserDescVO> userDescVOList, List<Issue> issueList, List<UserDescVO> teacherList) {

        /**
         put("0", "学院名称");
         put("1", "学生班级");
         put("2", "学号");
         put("3", "学生姓名");
         put("4", "指导教师姓名");
         put("5", "指导教师职称");
         put("6", "毕业设计(论文)课题名称");

         put("7", "课题来源");   //父
         put("8", "社会服务");   //子1
         put("9", "科研项目");   //子2
         put("10", "其他来源");  //子3

         put("11", "课题类型");   //父
         put("12", "设计");      //子1
         put("13", "论文");      //子2
         put("14", "其他类型");  //子3

         put("14", "备注");
         */
        List<Map<String, Object>> mapList = new ArrayList<>();
        Map<String, Object> map;
        Info info;
        for (UserDescVO userDescVO : userDescVOList) {
            map = new HashMap<>();
            Map<String, Info> userInfoMap = infoListTransformerTypeKeyMap(userDescVO.getInfoList());
            //0. 学院名称
            map.put("0", "软件学院");
            //1. 学生班级
            info = userInfoMap.get(InfoType.Basic + IKEY.CLAZZ);
            map.put("1", info == null ? "" : info.getValue());
            //2. 学号
            map.put("2", userDescVO.getIdentity().getNoId());
            //3. 学生姓名
            map.put("3", userDescVO.getIdentity().getName());
            info = userInfoMap.get(InfoType.TOPIC +IKEY.TopicId);
            IssueVO issueVO = null;
            if (info != null) {
                issueVO = issueBO.getCacheIssueVO(Integer.parseInt(info.getValue()));
            }
            if (issueVO != null ) {
                //6.毕业设计(论文)课题名称
                map.put("6", issueVO.getIssue().getTitle());
                //7.社会服务
                map.put("7", "√");
            }
            info = userInfoMap.get(InfoType.Tea + IKEY.Guide);
            if (info != null){
                UserDescVO teacher = identityBO.getUserDesc(Integer.parseInt(info.getValue()));
                //4. 指导教师姓名
                map.put("4", teacher.getIdentity().getName());
                //5. 指导教师职称
                Map<String, Info> infoMap = infoListTransformerTypeKeyMap(teacher.getInfoList());
                Info pro = infoMap.get(InfoType.Basic + IKEY.PROFESSIONALLEVER);
                map.put("5", pro == null ? "" : ProfessionalLever.getMap().get(pro.getValue()) == null ? pro.getValue() : ProfessionalLever.getMap().get(pro.getValue()));
            }
            map.put("10", "√");
            mapList.add(map);
        }
        return mapList;
    }



    private Map<Integer, IssueVO> issueListTransformerMap(List<Issue> issueList) {
        Map<Integer, IssueVO> issueVOMap = new HashMap<>(issueList.size());
        IssueVO issueVO;
        IssueContent issueContent;
        for (Issue issue : issueList) {
            issueVO = new IssueVO();
            issueContent = JSONObject.parseObject(issue.getContent(), IssueContent.class);
            issue.setContent(null);
            issueVO.setIssue(issue);
            issueVO.setIssueContent(issueContent);
            issueVOMap.put(issue.getId(), issueVO);
        }
        return issueVOMap;
    }

    private Map<Integer, UserDescVO> userListTransformerMap(List<UserDescVO> userDescVOList) {
        Map<Integer, UserDescVO> map = new HashMap<>(userDescVOList.size());
        for (UserDescVO userDescVO : userDescVOList) {
            map.put(userDescVO.getIdentity().getId(), userDescVO);
        }
        return map;
    }

    private Map<String, Info> infoListTransformerTypeKeyMap(List<Info> infoList) {
        Map<String, Info> infoMap = new HashMap<>(infoList.size());
        for (Info info : infoList) {
            infoMap.put(info.getType() + info.getKey(), info);
        }
        return infoMap;
    }

    private List<Map<String, Object>> GradeStatusTransformer(List<UserDescVO> userDescVOList, List<Issue> issueList, List<UserDescVO> teacherList) {

        /**
         put("0", "学院名称");
         put("1", "学生班级");
         put("2", "学号");
         put("3", "学生姓名");
         put("4", "指导教师姓名");
         put("5", "指导教师职称");
         put("6", "毕业设计(论文)课题名称");
         put("7", "子标题");   //父
         put("7", "进度");   //父
         */
        List<Map<String, Object>> mapList = new ArrayList<>();
        Map<String, Object> map;
        Info info;
        for (UserDescVO userDescVO : userDescVOList) {
            map = new HashMap<>();
            Map<String, Info> userInfoMap = infoListTransformerTypeKeyMap(userDescVO.getInfoList());
            //0. 学院名称
            map.put("0", "软件学院");
            //1. 学生班级
            info = userInfoMap.get(InfoType.Basic + IKEY.CLAZZ);
            map.put("1", info == null ? "" : info.getValue());
            //2. 学号
            map.put("2", userDescVO.getIdentity().getNoId());
            //3. 学生姓名
            map.put("3", userDescVO.getIdentity().getName());
            info = userInfoMap.get(InfoType.TOPIC +IKEY.TopicId);
            IssueVO issueVO = null;
            if (info != null) {
                issueVO = issueBO.getCacheIssueVO(Integer.parseInt(info.getValue()));
            }
            if (issueVO != null ) {
                //6.毕业设计(论文)课题名称
                map.put("6", issueVO.getIssue().getTitle());
                //7.子标题
                Info topChildName = userInfoMap.get(InfoType.TOPIC + IKEY.ChildTopicName);
                if (topChildName != null){
                    map.put("7", topChildName.getValue());
                }
            }
            info = userInfoMap.get(InfoType.Tea + IKEY.Guide);
            if (info != null){
                UserDescVO teacher = identityBO.getUserDesc(Integer.parseInt(info.getValue()));
                map.put("4", teacher.getIdentity().getName());
                Map<String, Info> infoMap = infoListTransformerTypeKeyMap(teacher.getInfoList());
                Info pro = infoMap.get(InfoType.Basic + IKEY.PROFESSIONALLEVER);
                map.put("5", pro == null ? "" : ProfessionalLever.getMap().get(pro.getValue()) == null ? pro.getValue() : ProfessionalLever.getMap().get(pro.getValue()));
            }

             Info  infoOne = userInfoMap.get(InfoType.GRADE + IKEY.SYSTEM_GRADE);
             Info  infoTwo = userInfoMap.get(InfoType.GRADE + GradeTimeType.SYSTEM_GRADE_TWO.getKey());
             Info  infoThree = userInfoMap.get(InfoType.GRADE + GradeTimeType.REPLY_GRADE_ONE.getKey());
             Info  infoFive = userInfoMap.get(InfoType.GRADE + GradeTimeType.REPLY_GRADE_TWO.getKey());
             Info  infoFour = userInfoMap.get(InfoType.GRADE + IKEY.GRADE_STOP_KEY);
            if (infoFour == null){
                if (infoOne == null){
                    map.put("8", "未操作");
                }else{
                    if (infoTwo != null){
                        map.put("8", "二次系统验收");
                    }else if (infoThree != null){
                        map.put("8", "进入一辩");
                    }else if(infoFive != null){
                        map.put("8", "进入二辩");
                    }
                }
            }else{
                map.put("8", "终止答辩");
            }

            mapList.add(map);
        }
        return mapList;
    }

    private List<Map<String, Object>> getGuideStudent(List<UserDescVO> userDescVOList){
        /**
         put("0", "序号");
         put("1", "学生班级");
         put("2", "学号");
         put("3", "学生姓名");
         put("4", "指导教师姓名");
         put("5", "设计(论文)课题名称");

         put("6", "课题来源");   //父
         put("7", "社会服务");   //子1
         put("8", "科研项目");   //子2
         put("9", "其他来源");  //子3

         put("10", "论文类型");   //父
         put("11", "设计");      //子1
         put("12", "论文");      //子2
         put("13", "其他类型");  //子3

         put("14", "指导成绩");
         put("15", "评阅成绩");
         put("16", "答辩成绩");
         put("17", "总评成绩");
         put("18", "备注");
         */
        List<Map<String, Object>> mapList = new ArrayList<>();
        Map<String, Object> map;
        Info info;
        int i = 1;
        for (UserDescVO userDescVO : userDescVOList) {
            map = new HashMap<>();
            Map<String, Info> userInfoMap = infoListTransformerTypeKeyMap(userDescVO.getInfoList());
            //0. 序号
            map.put("0", i++);
            //1. 学生班级
            info = userInfoMap.get(InfoType.Basic + IKEY.CLAZZ);
            map.put("1", info == null ? "" : info.getValue());
            //2. 学号
            map.put("2", userDescVO.getIdentity().getNoId());
            //3. 学生姓名
            map.put("3", userDescVO.getIdentity().getName());
            //4.指导教师
            info = userInfoMap.get(InfoType.Tea +IKEY.GuideName);
            map.put("4", info == null ? "" : info.getValue());
            //5 设计(论文)课题名称
            info = userInfoMap.get(InfoType.TOPIC + IKEY.TopicName);
            map.put("5", info == null ? "" : info.getValue());
            //子标题处理
            info = userInfoMap.get(InfoType.TOPIC + IKEY.ChildTopicName);
            if (info != null){
                String topicName = String.valueOf(map.get("5"));
                if (StringUtils.isNotBlank(topicName) && StringUtils.isNotBlank(info.getValue())){
                    topicName = topicName + "-" + info.getValue();
                    map.remove("5");
                    map.put("5", topicName);
                }
            }
            //处理课题类型 和 论文类型
            info = userInfoMap.get(InfoType.TOPIC +IKEY.TopicId);
            IssueVO issueVO = null;
            if (info != null) {
                issueVO = issueBO.getCacheIssueVO(Integer.parseInt(info.getValue()));
            }
            if (issueVO != null ) {
                switch (issueVO.getIssue().getKind()){
                    //科研项目
                    case Research:
                        map.put("7", "√");
                        break;
                    //社会服务
                    case Social:
                        map.put("6", "√");
                        break;

                }
                if (issueVO.getIssue().getType().equals("设计")){
                    map.put("9", "√");
                }else if (issueVO.getIssue().getType().equals("研究")){
                    map.put("10", "√");
                }else{
                    map.put("11", "√");
                }
            }
            //指导成绩
            info = userInfoMap.get(InfoType.GRADE + IKEY.GUIDE_GRADE);
            map.put("12", info == null ? "0" : info.getValue());
            //评阅成绩
            info = userInfoMap.get(InfoType.GRADE + IKEY.REPORT_GRADE);
            map.put("13", info == null ? "0" : info.getValue());
            //答辩成绩
            info = userInfoMap.get(InfoType.GRADE + IKEY.REPLY_GRADE);
            map.put("14", info == null ? "0" : info.getValue());
            //总成绩
            info = userInfoMap.get(InfoType.GRADE + IKEY.FINAL_REPLY_GRADE);
            map.put("15", info == null ? "0" : info.getValue());
            mapList.add(map);
        }
        return mapList;
    }
}
